package com.tanhua.dubbo.api.mongo;

import com.tanhua.domain.mongo.Friend;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.RecommendQuanzi;
import com.tanhua.domain.mongo.TimeLine;
import com.tanhua.domain.vo.PageResult;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 动态的服务
 */
@Service
public class PublishApiImpl implements PublishApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 发布动态
     *
     * @param pojo
     */
    @Override
    public void add(Publish pojo) {
        //1. 添加动态表
        //1.1 完善动态信息, 创建时间
        // 同一个业务的时间必须保持一致
        long timeMillis = System.currentTimeMillis();
        pojo.setCreated(timeMillis);
        //1.2 保存到动态表
        mongoTemplate.insert(pojo);
        //1.3 获取新增的动态id
        ObjectId publishId = pojo.getId();
        //2. 添加到登录用户的时间线表
        //2.1 拼接登录用户的时间线表名quanzi_time_line_{userId}
        String myTimelineCollectionName = "quanzi_time_line_" + pojo.getUserId();
        //2.2 构建timeline对象
        TimeLine myTimeline = new TimeLine();
        myTimeline.setPublishId(publishId);
        myTimeline.setUserId(pojo.getUserId());
        myTimeline.setCreated(timeMillis);
        //2.3 添加
        mongoTemplate.insert(myTimeline, myTimelineCollectionName);

        //3. 添加好友时间线表,
        // TODO 如果有1000个好友，性能如何? 使用MQ来异步解耦
        //3.1 查询好友id
        //3.2 构建好友查询的条件, userId=登录用户id
        Query query = new Query(Criteria.where("userId").is(pojo.getUserId()));
        List<Friend> friendList = mongoTemplate.find(query, Friend.class);
        //3.3 非空判断，如果有好友
        if(!CollectionUtils.isEmpty(friendList)) {
            //3.4 遍历好友id
            for (Friend friend : friendList) {
                //3.5 构建好友timeline的对象
                TimeLine friendTimeline = new TimeLine();
                friendTimeline.setPublishId(publishId);
                friendTimeline.setUserId(pojo.getUserId());
                friendTimeline.setCreated(timeMillis);
                //3.6 拼接好友时间线表名
                String collectionName = "quanzi_time_line_" + friend.getFriendId();
                //3.7 添加到好友时间线表
                mongoTemplate.insert(friendTimeline, collectionName);
            }
        }
    }

    /**
     * 通过登录用户id 分页查询好友动态得到的是pageResult
     *
     * @param loginUserId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult queryFriendPublishList(Long loginUserId, Long page, Long pageSize) {
        //1. 查询登录自己的时间线表
        //1.2. 拼接时间线表的名称
        String collectionName = "quanzi_time_line_" + loginUserId;
        Query query = new Query();
        //1.3 统计总数
        long total = mongoTemplate.count(query, collectionName);
        //1.4 总数>0
        List<Publish> publishList = new ArrayList<>();
        if(total > 0) {
            //1.5 设置分页参数
            query.skip((page-1)*pageSize).limit(pageSize.intValue());
            //1.6 按创建日期降序
            query.with(Sort.by(Sort.Order.desc("created")));
            //1.7 分页查询, 得到结果集
            List<TimeLine> timeLineList = mongoTemplate.find(query, TimeLine.class, collectionName);
            //2. 分页结果集的非空判断,
            if(!CollectionUtils.isEmpty(timeLineList)) {
                //2.1 有结果集,获取所有的动态id
                List<ObjectId> publishIds = timeLineList.stream().map(TimeLine::getPublishId).collect(Collectors.toList());
                //3. 查询动态表
                //3.1 构建动态表的查询条件_id in 动态id集合, mongodb通过id批量查询 > 乱序
                Query publishQuery = new Query(Criteria.where("_id").in(publishIds));
                //3.2 按时间降序
                publishQuery.with(Sort.by(Sort.Order.desc("created")));
                //3.3 查询动态表，得到动态结果集
                publishList = mongoTemplate.find(publishQuery, Publish.class);
            }
        }
        //4. 构建pageResult返回
        return PageResult.pageResult(page, pageSize, publishList, total);
    }

    /**
     * 通过登录用户id 分页查询推荐给登录用户的动态
     *
     * @param loginUserId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult queryRecommendPublishList(Long loginUserId, Long page, Long pageSize) {
        //1. 查询推荐动态表, 条件是userId=登录用户id
        Query query = new Query(Criteria.where("userId").is(loginUserId));
        //1.3 统计总数
        long total = mongoTemplate.count(query, RecommendQuanzi.class);
        //1.4 总数>0
        List<Publish> publishList = new ArrayList<>();
        if(total > 0) {
            //1.5 设置分页参数
            query.skip((page-1)*pageSize).limit(pageSize.intValue());
            //1.6 按创建日期降序
            query.with(Sort.by(Sort.Order.desc("created")));
            //1.7 分页查询, 得到结果集
            List<RecommendQuanzi> recommendQuanziList = mongoTemplate.find(query, RecommendQuanzi.class);
            //2. 分页结果集的非空判断,
            if(!CollectionUtils.isEmpty(recommendQuanziList)) {
                //2.1 有结果集,获取所有的动态id
                List<ObjectId> publishIds = recommendQuanziList.stream().map(RecommendQuanzi::getPublishId).collect(Collectors.toList());
                //3. 查询动态表
                //3.1 构建动态表的查询条件_id in 动态id集合, mongodb通过id批量查询 > 乱序
                Query publishQuery = new Query(Criteria.where("_id").in(publishIds));
                //3.2 按时间降序
                publishQuery.with(Sort.by(Sort.Order.desc("created")));
                //3.3 查询动态表，得到动态结果集
                publishList = mongoTemplate.find(publishQuery, Publish.class);
            }
        }
        //4. 构建pageResult返回
        return PageResult.pageResult(page, pageSize, publishList, total);
    }

    /**
     * 查询我发布的动态或某个用户发布的动态
     *
     * @param searchUserId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult queryUserPublishList(Long searchUserId, Long page, Long pageSize) {
        //1. 查询登录自己的时间线表
        //1.2. 拼接时间线表的名称
        String collectionName = "quanzi_time_line_" + searchUserId;
        // 作者是谁
        Query query = new Query(Criteria.where("userId").is(searchUserId));
        //1.3 统计总数
        long total = mongoTemplate.count(query, collectionName);
        //1.4 总数>0 5   10
        List<Publish> publishList = new ArrayList<>();
        if(total > 0) {
            //1.5 设置分页参数
            query.skip((page-1)*pageSize).limit(pageSize.intValue());
            //1.6 按创建日期降序, 今天 10条， 昨天发了10
            query.with(Sort.by(Sort.Order.desc("created")));
            //1.7 分页查询, 得到结果集, 2页
            List<TimeLine> timeLineList = mongoTemplate.find(query, TimeLine.class, collectionName);
            //2. 分页结果集的非空判断,
            if(!CollectionUtils.isEmpty(timeLineList)) {
                //2.1 有结果集,获取所有的动态id
                List<ObjectId> publishIds = timeLineList.stream().map(TimeLine::getPublishId).collect(Collectors.toList());
                //3. 查询动态表
                //3.1 构建动态表的查询条件_id in 动态id集合, mongodb通过id批量查询 > 乱序
                Query publishQuery = new Query(Criteria.where("_id").in(publishIds));
                //3.2 按时间降序
                publishQuery.with(Sort.by(Sort.Order.desc("created")));
                //3.3 查询动态表，得到动态结果集
                publishList = mongoTemplate.find(publishQuery, Publish.class);
            }
        }
        //4. 构建pageResult返回
        return PageResult.pageResult(page, pageSize, publishList, total);
    }

    /**
     * 通过id查询动态信息
     *
     * @param publishId
     * @return
     */
    @Override
    public Publish findById(String publishId) {
        return mongoTemplate.findById(new ObjectId(publishId), Publish.class);
    }
}
